using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using log4net;
using Sedna.Core.Security;
using Sedna.Domain;

namespace Sedna.Core.Controller.Configurations
{
    public class MonetaryAmountStringParser : IDataTranslator
    {
        private ILog log = LogManager.GetLogger(typeof(MonetaryAmountStringParser));

        private double precision = 4;
        private IPrincipalWrapper principalWrapper;
        private string defaultValue = "0";
        private bool breakOnNull = false;

        #region Properties
        
        public IPrincipalWrapper PrincipalWrapper
        {
            set { principalWrapper = value; }
        }

        public double Precision
        {
            set { precision = value; }
        }

        public string DefaultValue
        {
            set { defaultValue = value; }
        }

        public bool BreakOnNull
        {
            set { breakOnNull = value; }
        }

        #endregion

        #region Translate
        
        public object Translate(Control control, object value)
        {
            return Translate(control, value, null);
        }

        public object Translate(Control control, object value, Type targetType)
        {
            if (targetType == null)
            {
                string errorMessage = "TargetType is null";
                log.Error(errorMessage);
                throw new ControllerConfigurationException(errorMessage);
            }

            if (value == null)
                value = defaultValue;

            string strValue = value as string;

            if (strValue != null)
            {
                strValue = strValue.ToUpper().Replace("$", "").Trim();
                strValue = strValue.ToUpper().Replace(MonetaryAmount.USD, "").Trim();
                strValue = strValue.ToUpper().Replace(MonetaryAmount.RUR, "").Trim();
                strValue = strValue.ToUpper().Replace(MonetaryAmount.GBP, "").Trim();
                strValue = strValue.ToUpper().Replace(MonetaryAmount.EUR, "").Trim();
                strValue.Replace(" ", "");
                if (strValue.Length == 0)
                    value = defaultValue;
                else
                {
                    Regex r = new Regex("^([0-9.,]*)");
                    Match m = r.Match(strValue);
                    value = (m.Groups[1].Value.Length != strValue.Length) ? defaultValue : m.Groups[1].Value;

                    decimal factor = (decimal)(Math.Pow(10, precision));
                    try
                    {
                        value = Math.Floor(Convert.ToDecimal(value, principalWrapper.Culture) * factor) / factor;
                    }
                    catch
                    {
                        value = defaultValue;
                    }
                }
            }
            else
            {
                string errorMessage = string.Format("Not supporting value type: {0}", value.GetType());
                log.Error(errorMessage);
                throw new ControllerConfigurationException(errorMessage);
            }

            if (value == null && breakOnNull)
                return value;

            if (targetType == typeof(MonetaryAmount))
            {
                try
                {
                    return MonetaryAmount.CreateFromValue(Convert.ToDecimal(value, principalWrapper.Culture));
                }
                catch (Exception e)
                {
                    string errorMessage = string.Format("Error while trying to convert a value '{0}' to 'decimal' type: {1}", value, e.Message);
                    log.Error(errorMessage);
                    throw new ControllerConfigurationException(errorMessage);
                }
            }

            if (targetType == typeof(decimal) || targetType == typeof(double) || targetType == typeof(long))
            {
            }
            else
            {
                targetType = typeof(decimal);
                string errorMessage = string.Format("Not supporting TargetType: {0}. Used type decimal.", targetType);
                log.Error(errorMessage);
            }

            try
            {
                return Convert.ChangeType(value, targetType, principalWrapper.Culture);
            }
            catch (Exception e)
            {
                string errorMessage = string.Format("Error while trying to convert a value '{0}' to '{1}' type: {2}", value, targetType, e.Message);
                log.Error(errorMessage);
                throw new ControllerConfigurationException(errorMessage);
            }
        }

        #endregion
    }
}
